package com.link.action;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;

import com.link.bean.LinkListBean;
import com.link.po.Account;
import com.link.po.Link;
import com.link.po.LinkType;
import com.others.util.Constants2;
import com.others.util.CookieUtils;
import com.others.util.RegExpValidator;

public class LinkListAction extends BaseAction {

    private static final long serialVersionUID = 8720945193140539723L;
    
    private static final String PREFIX_URL = "http://";
    
    private static final int MAX_LINK_TYPE_ID = 9999;
    
    public String list () {

        cookieUtils.getCookie(getRequest(), getSession(), getAuthenticationService());
        iniBaseInfo();
        initAddLinkForm();
        initLinkListForm();
        
        return LIST;
    }
    
    public String input () {
        cookieUtils.getCookie(getRequest(), getSession(), getAuthenticationService()); 
        iniBaseInfo();
        initAddLinkForm();
        initLinkListForm();
        
        if(!isLoginFailedFlag()) {
            setAddLinkFailedFlag(true);
        }
        return LIST;
    }
    
    private void initAddLinkForm() {
       if (getLink() == null) {
           setLink(new Link());
       }
       getLink().setUrl(PREFIX_URL);
       setLinkTypeList(getLinkService().getLinkTypeList());
    }

    public String update () {

        return UPDATE;
    }
    
    public String add () {
        
        Link link = getLink();
        LinkType linkType = getLinkService().getLinkTypebyId(getLinkTypeId());
        link.setLinkType(linkType);
        Account account = (Account) getSession().get(ACCOUNT_SESSION);
        
        //validation:
        if (account == null) {
            addActionError(getText(ERROR_NOT_LOGIN));
            
            setAddLinkFailedFlag(true);
            return FAILED;
        }
        
        if (StringUtils.isBlank(link.getName())) {
            List<Object> args = new ArrayList<Object>();
            args.add("Link Name");
            addActionError(getText(ERROR_IS_REQUIRED, args));
            
            setAddLinkFailedFlag(true);
            return FAILED;
        }
        if (StringUtils.isBlank(link.getUrl())) {
            List<Object> args = new ArrayList<Object>();
            args.add("Link URL");
            addActionError(getText(ERROR_IS_REQUIRED, args));
            
            setAddLinkFailedFlag(true);
            return FAILED;
        } else if(!RegExpValidator.isURL(link.getUrl())){
            List<Object> args = new ArrayList<Object>();
            args.add("Link URL");
            addActionError(getText(ERROR_IS_INVALID, args));
            
            setAddLinkFailedFlag(true);
            return FAILED;
        }
        if (StringUtils.isBlank(link.getDescription())) {
            List<Object> args = new ArrayList<Object>();
            args.add("Link Description");
            addActionError(getText(ERROR_IS_REQUIRED, args));
            
            setAddLinkFailedFlag(true);
            return FAILED;
        }
       
        
        getLinkService().saveAccountLink(link, account);

        return ADD;
    }
    
    
    //for LinkList.jsp
    private void initLinkListForm() {
        
        List<List<LinkListBean>> finalBeanList = new ArrayList<List<LinkListBean>>();
        
        List<Link> originalLinkList = new ArrayList<Link>();
        
        Account account = (Account) getSession().get(ACCOUNT_SESSION);

        if (account != null && account.getId() != 0) {
            originalLinkList = getLinkService().getLinkListByAccountId(account.getId());
            
            List<Link> defaultLinkList = getLinkService().getDefaultLinkList();
            for (Link link : defaultLinkList) {
                boolean matchFalg = false;
                for (Link tempLink : originalLinkList) {
                    if (link.getId() == tempLink.getId()) {
                        matchFalg = true;
                        break;
                    }
                }

                if (!matchFalg) {
                    originalLinkList.add(link);
                }
            }
        } else {
            originalLinkList = getLinkService().getDefaultLinkList(); 
        }


        Map<String, List<Link>> linkMap = new HashMap<String, List<Link>>();
        if (!originalLinkList.isEmpty()) {
            for (Link link : originalLinkList) {
                String linkTypeName = link.getLinkType().getName();

                if(!linkMap.keySet().contains(linkTypeName)) {
                    List<Link> subLinkList = new ArrayList<Link>();
                    linkMap.put(linkTypeName, subLinkList);
                }
                
                linkMap.get(linkTypeName).add(link);
            }
            
        }

        List<LinkListBean> beanList = new ArrayList<LinkListBean>();
        for (String linkTypeName : linkMap.keySet()) {
            LinkListBean linkListBean = new LinkListBean();
            linkListBean.setLinkList(linkMap.get(linkTypeName));
            linkListBean.setLinkTypeName(linkTypeName);
            
            //Morgan: In fact, here all Link has the same link type id.
            //Another thing: this is not good implementation, because, we filter LinkList with type name,
            //But here we get it by link type id. (Every Link Type has different id and name.)
            
            if(linkMap.get(linkTypeName) != null && !linkMap.get(linkTypeName).isEmpty()) {
                linkListBean.setLinkTypeId(linkMap.get(linkTypeName).get(0).getId());
            } else {
                linkListBean.setLinkTypeId(MAX_LINK_TYPE_ID);
            }

            
            beanList.add(linkListBean);
        }

        Collections.sort(beanList, new Comparator<LinkListBean>() {
            public int compare(LinkListBean o1, LinkListBean o2) {
                List<Link> list1 = o1.getLinkList();
                List<Link> list2 = o2.getLinkList();
                
                int totalNum1 = 0;
                int totalNum2 = 0;
                
                for (Link link1 : list1) {
                    totalNum1 = totalNum1 + link1.getNumClick();
                }
                
                for (Link link2 : list2) {
                    totalNum2 = totalNum2 + link2.getNumClick();
                }
                
                if (totalNum2 - totalNum1 != 0) {
                    return totalNum2 - totalNum1;
                } else {
                    return (o2.getLinkListSize() - o1.getLinkListSize());
                }
            }
        });
        
        
        List<LinkListBean> columnBeanList = null;
        int lastNum;
        if (beanList.size() % Constants2.LINK_LIST_COLUMN_NUM == 0) {
            lastNum = 0;
        } else {
            lastNum = Constants2.LINK_LIST_COLUMN_NUM - beanList.size() % Constants2.LINK_LIST_COLUMN_NUM;
        }
        
        for (int j = 0; j < lastNum; j++) {
            LinkListBean linkListBean = new LinkListBean();
            linkListBean.setLinkList(new ArrayList<Link>());
            linkListBean.setLinkTypeName("TODO" + j);
            linkListBean.setLinkTypeId(MAX_LINK_TYPE_ID);
            beanList.add(linkListBean);
        }

        int i = 0;
        for (LinkListBean linkListBean : beanList) {
            if (i % Constants2.LINK_LIST_COLUMN_NUM == 0) {
                columnBeanList = new ArrayList<LinkListBean>();
                finalBeanList.add(columnBeanList);
            }
            i++;
            columnBeanList.add(linkListBean);
        }

        setBeanList(finalBeanList);
        
    }
    

    private List<List<LinkListBean>> beanList;
    private List<LinkType> linkTypeList;
    private Link link;
    private int linkTypeId;
    private CookieUtils cookieUtils = new CookieUtils();

    public List<List<LinkListBean>> getBeanList() {
        return beanList;
    }

    public void setBeanList(List<List<LinkListBean>> beanList) {
        this.beanList = beanList;
    }

    public List<LinkType> getLinkTypeList() {
        return linkTypeList;
    }

    public void setLinkTypeList(List<LinkType> linkTypeList) {
        this.linkTypeList = linkTypeList;
    }

    public int getLinkTypeId() {
        return linkTypeId;
    }

    public void setLinkTypeId(int linkTypeId) {
        this.linkTypeId = linkTypeId;
    }

    public Link getLink() {
        return link;
    }

    public void setLink(Link link) {
        this.link = link;
    }
    
}
